package com.nifostasky.common.oauth;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.nifostasky.common.utils.JWTUtil;
import com.nifostasky.entity.SysUser;
import com.nifostasky.service.ShiroService;
import io.jsonwebtoken.Claims;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.Set;

/**
 * 实现realm
 */
@Component
public class OAuthRealm extends AuthorizingRealm {
    @Autowired
    private ShiroService service;

    /**
     * 这个很重要,一定要写
     * 每一个Ream都有一个supports方法，用于检测是否支持此Token,为true表示支持
     * @param token
     * @return
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof OAuthToken;
    }

    /**
     * 授权,仅在鉴权的时候会调用
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //获取用户信息
        SysUser sysUser = (SysUser) principalCollection.getPrimaryPrincipal();
        //获取用户id
        Long userId = sysUser.getUserId();
        //根据userid获取用户的权限信息
        Set<String> permissions = service.getUserPermissions(userId);
        //添加到shiro的权限构造器中
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.setStringPermissions(permissions);
        return info;
    }

    /**
     * 认证,登录时会调用(访问接口的时候)
     * @param token
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        String accessToken = (String) token.getPrincipal();

        //验证token是否失效
        if (!JWTUtil.isValidToken(accessToken))
            throw new IncorrectCredentialsException("token有误,请重新登录");
        // 获取token中的用户信息(这里主要获取用户id)
        Claims claims = JWTUtil.parseJWT(accessToken);
        String subject = claims.getSubject();
        JSONObject jsonObject = JSON.parseObject(subject);
        if (!jsonObject.containsKey("userId"))
            throw new IncorrectCredentialsException("token有误,请重新登录");
        Long userId = jsonObject.getLong("userId");
        //通过用户id ,获取用户信息
        SysUser sysUser = service.queryUser(userId);
        //账号锁定
        if(sysUser.getStatus() == 0){
            throw new LockedAccountException("账号已被锁定,请联系管理员");
        }
        //将信息传递到权限验证方法中
        SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(sysUser, accessToken, getName());
        return info;
    }
}
